package org.utils.cmdline;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.utils.cmdline.parameters.CommandParameter;
import org.utils.cmdline.parameters.MessageParameter;
import org.utils.cmdline.parameters.MultiValueParameter;
import org.utils.cmdline.parameters.SingleValueParameter;
import org.utils.cmdline.parameters.TerminalParameter;

public abstract class GenericCommand extends CommandBase implements Runnable {

    private Map parseMap;

//accessing
    public Map parseMap() {
		return parseMap;
    }

    public void parseMap(Map aMap) {
		parseMap = aMap;
    }

    public void addToParseMap(Object key, CommandParameter value) {
		parseMap().put(key, value);
    }

    public CommandParameter parseValue(String value) {
		return valueOrDefault((CommandParameter)parseMap.get(value), value);
    }

    public boolean isParameterSet(String name) {
      return parseMap.containsKey(name) && ((CommandParameter) parseMap.get(name)).beingUsed();
    }

    public CommandParameter getParameter(String name)
    {
      return (CommandParameter) parseMap.get(name);
    }

    public String getParameterValue(String name)
    {
      return ((SingleValueParameter) parseMap.get(name)).value();
    }

    public String[] getParameterValues(String name)
    {
      return ((MultiValueParameter) parseMap.get(name)).values();
    }

    public CommandParameter valueOrDefault(CommandParameter parameter,
							String value) {
	return (CommandParameter)defaultWhenNull(
			parameter, defaultParameter(value));
    }

//parsing
    public Map defaultParseMap() {
		CommandParameter param = newHelpParameter();
		Map map = newMap();
		map.put("-h", param);
		map.put("-help", param);
		map.put("-?", param);
		return map;
    }

    public void parseArguments(String[] arguments) {
	parseArguments(asList(arguments));
	enactArguments();
    }

    public void parseArguments(List arguments) {
	parseArguments(arguments.listIterator());
    }

    public void parseArguments(Iterator iterator) {
	while (iterator.hasNext()) {
	    parseArgument(iterator,(String)iterator.next());
	}
    }

    public void parseArgument(Iterator iterator,String argument) {
		CommandParameter parameter = parseValue(argument);
		parameter.loadAdditionalArguments(iterator);
    }

    public void enactArguments() {
        enactArguments(parseMap());
    }

    public void enactArguments(Map pParseMap) {
        enactArguments(pParseMap.values());
    }

    public void enactArguments(Collection aCollection) {
        enactArguments(aCollection.iterator());
    }

    public void enactArguments(Iterator iterator) {
		while (iterator.hasNext()) {
		    enactArgument((CommandParameter)iterator.next());
		}
    }

    public void enactArgument(CommandParameter aParameter) {
	aParameter.enact(this);
    }

//constants
    public String helpMessage() {
		return "Usage is: <command> [-h | -help | -?]";
//		StringBuffer buffer = new StringBuffer();
//		buffer.append("Usage is: ").append(StringUtils.newLine());
//		buffer.append("<command> [-h | -help | -?]").append(StringUtils.newLine());
//		buffer.append("<command> [");
//		Iterator iterator = parseMap.keySet().iterator();
//		while (iterator.hasNext())
//		{
//			String key = (String) iterator.next();
//			if (!key.equalsIgnoreCase("-h")
//				&& !key.equalsIgnoreCase("-help")
//				&& !key.equalsIgnoreCase("-?"))
//				buffer.append(key).append(" ");
//		}
//		buffer.append("]").append(StringUtils.newLine());
//		return buffer.toString();
    }
    
    public boolean validateParams()
    {
    	return true;
    }

//collaborators
    public CommandParameter defaultParameter(String value) {
		CommandParameter parameter =
		    new MessageParameter(0,"Unkown option found \"" + value +
			    "\" skipping...");
		if (!parseMap().containsKey(value)) {
		    addToParseMap(value,parameter);
		}
		return parameter;
    }

    public TerminalParameter newHelpParameter() {
		return new TerminalParameter(0, helpMessage());
    }

//construction
    public GenericCommand() {
		parseMap(defaultParseMap());
    }
    
    public void exit(String message) {
    	System.err.println(message);
    	System.err.println(helpMessage());
    	System.exit(1);
	}
}

